package org.yaac.shared.property;

import static com.google.common.collect.Lists.newArrayList;

import java.util.Arrays;
import java.util.List;

import org.yaac.shared.egql.ResultCell;
import org.yaac.shared.egql.ResultCell.ResultCellFactory;

import com.google.gwt.safehtml.shared.SafeHtmlUtils;

/**
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
//TODO : implement ordering based on logics documented at http://code.google.com/appengine/docs/java/datastore/entities.html
public class BlobPropertyInfo extends PropertyInfo {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private Integer size;

	private String downloadPath;
	
	/**
	 * user can also define raw data directly
	 */
	private byte [] rawData;
	
	/**
	 * used by GWT
	 */
	@SuppressWarnings("unused")
	private BlobPropertyInfo(){}
	
	public BlobPropertyInfo(byte[] rawData) {
		super();
		this.rawData = rawData;
	}

	public BlobPropertyInfo(Integer size, String downloadPath) {
		super();
		this.size = size;
		this.downloadPath = downloadPath;
	}

	public Integer getSize() {
		return size;
	}

	public String getDownloadPath() {
		return downloadPath;
	}
	
	public byte[] getRawData() {
		return rawData;
	}

	@Override
	public int compareTo(PropertyInfo o) {
		// blob is not comparable
		return 0;
	}

	@Override
	public String asHtml() {
		// TODO : i18n
		if (rawData == null) {
			return "<a href='/download?path=" + SafeHtmlUtils.htmlEscape(downloadPath) + "' target='blank'>Blob size = " + size + " bytes</a>";	
		} else {
			return new String(rawData);
		}
	}

	@Override
	public ResultCell populateResultCell(ResultCellFactory factory) {
		ResultCell cell = super.populateResultCell(factory);
		cell.setType(PropertyType.BLOB);
		cell.setParent(null);
		cell.setChildren(null);
		cell.setPayload(Arrays.asList(size.toString(), downloadPath));
		return cell;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((downloadPath == null) ? 0 : downloadPath.hashCode());
		result = prime * result + Arrays.hashCode(rawData);
		result = prime * result + ((size == null) ? 0 : size.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		BlobPropertyInfo other = (BlobPropertyInfo) obj;
		if (downloadPath == null) {
			if (other.downloadPath != null)
				return false;
		} else if (!downloadPath.equals(other.downloadPath))
			return false;
		if (!Arrays.equals(rawData, other.rawData))
			return false;
		if (size == null) {
			if (other.size != null)
				return false;
		} else if (!size.equals(other.size))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "BlobPropertyInfo [size=" + size + ", downloadPath=" + downloadPath + ", rawData="
				+ Arrays.toString(rawData) + "]";
	}

	@Override
	public String asExpression(FilePlaceHolder placeHolder) {
		if (rawData == null) {
			return "blob(" + placeHolder.next() + ")";
		} else {
			return "blob('" + new String(rawData) + "')";
		}
	}

	@Override
	public List<String> downloadPaths() {
		if (rawData == null) {
			return newArrayList(this.downloadPath);
		} else {
			return newArrayList();
		}
	}
}
